﻿#region Copyright (c) 2010 R. Uittenbosch
/*
* Copyright (C) 2010 R. Uittenbosch
* 
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
* associated documentation files (the "Software"), to deal in the Software without restriction, including 
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the 
* following conditions:
* 
* The above copyright notice and this permission notice shall be included in all copies or substantial 
* portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 
* EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#endregion

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using OAuth.Net.Mobile.Common;
using OAuth.Net.Mobile.Components;
using Microsoft.Win32;
using System.IO;
using Microsoft.Practices.ServiceLocation;


namespace LinkedService.Mobile
{
  /// <summary>
  /// Storage enabler to store tokens in the windows registry
  /// </summary>
  public class RegistryTokenStore : IOAuthTokenStore
  {

    #region Private Variables
    private const string RegEntryKey = @"Software\LinkedIn for Windows Mobile\";

    private string Key { get; set; }
    private string Secret { get; set; }
    private List<IToken> tokens = new List<IToken>();

    private IConfiguration Configuration
    {
      get
      {
        return ServiceLocator.Current.GetInstance<IConfiguration>();
      }
    }
    #endregion

    #region Constructor
    public RegistryTokenStore(string key, string secret)
    {
      Key = key;
      Secret = secret;
      CurrentStatus = Status.NoTokens;
      LoadTokens();
    }
    #endregion

    #region ITokenStore
    public bool Add(IToken token)
    {
      if (!tokens.Contains(token))
      {
        // And save
        tokens.Add(token);
        StoreTokens();
        return true;
      }
      return false;

    }

    public IToken Get(TokenType type)
    {
      IToken result = null;
      foreach (IToken token in tokens)
      {
        if (token.Type == type)
          result = token;
      }
      return result;
    }

    public Status CurrentStatus { get; private set; }

    #endregion

    #region LoadTokens

    private void LoadTokens()
    {

      RegistryKey tokenKey = Registry.CurrentUser.OpenSubKey(RegEntryKey + @"\Tokens\" + Key + Secret);

      if (tokenKey != null)
      {
        string regKey = (string)tokenKey.GetValue(@"Key");
        if (regKey.CompareTo(Key) == 0)
        {
          // Check the secret
          if (tokenKey.GetValue(@"Secret") != null)
          {
            string regSecret = (string)tokenKey.GetValue(@"Secret");
            if (regSecret.CompareTo(Secret) == 0)
            {
              // Ok
              if (tokenKey.GetValue(@"Request") != null)
              {
                IToken requestToken = OAuth.Net.Mobile.Consumer.OAuthToken.Deserialize((string)tokenKey.GetValue
                  (@"Request"));
                tokens.Add(requestToken);
                CurrentStatus = Status.RequestTokenOk;
              }
              if (tokenKey.GetValue(@"Access") != null)
              {
                IToken accessToken = OAuth.Net.Mobile.Consumer.OAuthToken.Deserialize((string)tokenKey.GetValue
                  (@"Access"));
                tokens.Add(accessToken);
                CurrentStatus = Status.AccessTokenOk;
              }
              else
              {
                // In case no accesstoken has been found, no tokens should exist
                CurrentStatus = Status.NoTokens;
              }
            }
          }
        }
      }

      if (CurrentStatus != Status.AccessTokenOk)
      {
        if (File.Exists(@"Data\" + "requestToken.txt"))
        {
          using (System.IO.TextReader r = new System.IO.StreamReader(@"Data\" + "requestToken.txt"))
          {
            tokens.Add(OAuth.Net.Mobile.Consumer.OAuthToken.Deserialize(r.ReadToEnd()));
            r.Close();
          }
        }
        if (File.Exists(@"Data\" + "accessToken.txt"))
        {
          using (System.IO.TextReader r = new System.IO.StreamReader(@"Data\" + "accessToken.txt"))
          {
            tokens.Add(OAuth.Net.Mobile.Consumer.OAuthToken.Deserialize(r.ReadToEnd()));
            r.Close();
          }
          CurrentStatus = Status.AccessTokenOk;
        }
        StoreTokens();
      }
    }
    #endregion

    #region StoreTokens
    private void StoreTokens()
    {

      RegistryKey tokenKey = Registry.CurrentUser.CreateSubKey(RegEntryKey + @"Tokens\" + Key + Secret);
      if (tokenKey != null)
      {
        tokenKey.SetValue("Key", Key);
        tokenKey.SetValue("Secret", Secret);
        foreach (IToken token in tokens)
        {
          string tokenstr = OAuth.Net.Mobile.Consumer.OAuthToken.Serialize((OAuth.Net.Mobile.Consumer.OAuthToken)token);
          if (token.Type == TokenType.Request)
          {
            tokenKey.SetValue("Request", tokenstr);
          }
          else
          {
            tokenKey.SetValue("Access", tokenstr);
          }
        }
      }
    }
    #endregion
  }
}
